using Microsoft.Extensions.Logging;
using SumerCoreDevOps.Domain.Entities;
using SumerCoreDevOps.Infrastructure.Data;
using System.Text.Json;

namespace SumerCoreDevOps.Infrastructure.Logging;

/// <summary>
/// 节点操作日志管理器
/// </summary>
public class NodeOperationLogManager
{
    private readonly FreeSQLProvider _dbProvider;
    private readonly ILogger<NodeOperationLogManager> _logger;

    public NodeOperationLogManager(FreeSQLProvider dbProvider, ILogger<NodeOperationLogManager> logger)
    {
        _dbProvider = dbProvider;
        _logger = logger;
    }

    /// <summary>
    /// 记录节点操作日志
    /// </summary>
    public async Task<NodeOperationLog> LogOperationAsync(
        string nodeId,
        string operationType,
        string? nodeName = null,
        string? taskId = null,
        long? pipelineInstanceId = null,
        string status = "Success",
        string? message = null,
        object? details = null,
        string? errorMessage = null,
        string? ipAddress = null,
        string? userAgent = null,
        string logLevel = "Info")
    {
        try
        {
            var log = new NodeOperationLog
            {
                NodeId = nodeId,
                NodeName = nodeName,
                OperationType = operationType,
                TaskId = taskId,
                PipelineInstanceId = pipelineInstanceId,
                Status = status,
                Message = message,
                Details = details != null ? JsonSerializer.Serialize(details) : null,
                ErrorMessage = errorMessage,
                IpAddress = ipAddress,
                UserAgent = userAgent,
                LogLevel = logLevel,
                StartTime = DateTime.UtcNow,
                EndTime = DateTime.UtcNow,
                DurationMs = 0,
                CreatedAt = DateTime.UtcNow
            };

            await _dbProvider.Orm.Insert(log).ExecuteAffrowsAsync();

            _logger.LogDebug("记录节点操作日志: NodeId={NodeId}, Type={Type}, Status={Status}",
                nodeId, operationType, status);

            return log;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "记录节点操作日志失败: NodeId={NodeId}, Type={Type}", nodeId, operationType);
            throw;
        }
    }

    /// <summary>
    /// 开始记录一个长时间运行的操作
    /// </summary>
    public async Task<NodeOperationLog> StartOperationAsync(
        string nodeId,
        string operationType,
        string? nodeName = null,
        string? taskId = null,
        long? pipelineInstanceId = null,
        string? message = null,
        object? details = null,
        string? ipAddress = null,
        string? userAgent = null)
    {
        var log = new NodeOperationLog
        {
            NodeId = nodeId,
            NodeName = nodeName,
            OperationType = operationType,
            TaskId = taskId,
            PipelineInstanceId = pipelineInstanceId,
            Status = "InProgress",
            Message = message,
            Details = details != null ? JsonSerializer.Serialize(details) : null,
            IpAddress = ipAddress,
            UserAgent = userAgent,
            LogLevel = "Info",
            StartTime = DateTime.UtcNow,
            CreatedAt = DateTime.UtcNow
        };

        await _dbProvider.Orm.Insert(log).ExecuteAffrowsAsync();
        return log;
    }

    /// <summary>
    /// 完成一个长时间运行的操作
    /// </summary>
    public async Task CompleteOperationAsync(
        long logId,
        string status = "Success",
        string? message = null,
        string? errorMessage = null)
    {
        var log = await _dbProvider.Orm.Select<NodeOperationLog>()
            .Where(l => l.Id == logId)
            .FirstAsync();

        if (log == null)
        {
            _logger.LogWarning("操作日志不存在: LogId={LogId}", logId);
            return;
        }

        log.Status = status;
        log.EndTime = DateTime.UtcNow;
        log.DurationMs = (int)(log.EndTime.Value - log.StartTime).TotalMilliseconds;

        if (!string.IsNullOrEmpty(message))
        {
            log.Message = message;
        }

        if (!string.IsNullOrEmpty(errorMessage))
        {
            log.ErrorMessage = errorMessage;
            log.LogLevel = "Error";
        }

        await _dbProvider.Orm.Update<NodeOperationLog>()
            .SetSource(log)
            .ExecuteAffrowsAsync();
    }

    /// <summary>
    /// 根据节点 ID 获取操作日志
    /// </summary>
    public async Task<List<NodeOperationLog>> GetLogsByNodeIdAsync(
        string nodeId,
        int limit = 100,
        int offset = 0)
    {
        return await _dbProvider.Orm.Select<NodeOperationLog>()
            .Where(l => l.NodeId == nodeId)
            .OrderByDescending(l => l.CreatedAt)
            .Skip(offset)
            .Limit(limit)
            .ToListAsync();
    }

    /// <summary>
    /// 根据任务 ID 获取操作日志
    /// </summary>
    public async Task<List<NodeOperationLog>> GetLogsByTaskIdAsync(string taskId)
    {
        return await _dbProvider.Orm.Select<NodeOperationLog>()
            .Where(l => l.TaskId == taskId)
            .OrderBy(l => l.CreatedAt)
            .ToListAsync();
    }

    /// <summary>
    /// 根据流水线实例 ID 获取操作日志
    /// </summary>
    public async Task<List<NodeOperationLog>> GetLogsByPipelineInstanceIdAsync(long pipelineInstanceId)
    {
        return await _dbProvider.Orm.Select<NodeOperationLog>()
            .Where(l => l.PipelineInstanceId == pipelineInstanceId)
            .OrderBy(l => l.CreatedAt)
            .ToListAsync();
    }

    /// <summary>
    /// 根据操作类型获取日志
    /// </summary>
    public async Task<List<NodeOperationLog>> GetLogsByOperationTypeAsync(
        string operationType,
        int limit = 100)
    {
        return await _dbProvider.Orm.Select<NodeOperationLog>()
            .Where(l => l.OperationType == operationType)
            .OrderByDescending(l => l.CreatedAt)
            .Limit(limit)
            .ToListAsync();
    }

    /// <summary>
    /// 获取错误日志
    /// </summary>
    public async Task<List<NodeOperationLog>> GetErrorLogsAsync(
        DateTime? startDate = null,
        DateTime? endDate = null,
        int limit = 100)
    {
        var query = _dbProvider.Orm.Select<NodeOperationLog>()
            .Where(l => l.LogLevel == "Error" || l.Status == "Failed");

        if (startDate.HasValue)
        {
            query = query.Where(l => l.CreatedAt >= startDate.Value);
        }

        if (endDate.HasValue)
        {
            query = query.Where(l => l.CreatedAt <= endDate.Value);
        }

        return await query
            .OrderByDescending(l => l.CreatedAt)
            .Limit(limit)
            .ToListAsync();
    }

    /// <summary>
    /// 获取最近的日志
    /// </summary>
    public async Task<List<NodeOperationLog>> GetRecentLogsAsync(
        int limit = 50,
        string? logLevel = null,
        string? operationType = null)
    {
        var query = _dbProvider.Orm.Select<NodeOperationLog>();

        if (!string.IsNullOrEmpty(logLevel))
        {
            query = query.Where(l => l.LogLevel == logLevel);
        }

        if (!string.IsNullOrEmpty(operationType))
        {
            query = query.Where(l => l.OperationType == operationType);
        }

        return await query
            .OrderByDescending(l => l.CreatedAt)
            .Limit(limit)
            .ToListAsync();
    }

    /// <summary>
    /// 获取日志统计信息
    /// </summary>
    public async Task<NodeOperationLogStatistics> GetStatisticsAsync(
        DateTime? startDate = null,
        DateTime? endDate = null,
        string? nodeId = null)
    {
        var query = _dbProvider.Orm.Select<NodeOperationLog>();

        if (startDate.HasValue)
        {
            query = query.Where(l => l.CreatedAt >= startDate.Value);
        }

        if (endDate.HasValue)
        {
            query = query.Where(l => l.CreatedAt <= endDate.Value);
        }

        if (!string.IsNullOrEmpty(nodeId))
        {
            query = query.Where(l => l.NodeId == nodeId);
        }

        var logs = await query.ToListAsync();

        return new NodeOperationLogStatistics
        {
            TotalLogs = logs.Count,
            ErrorLogs = logs.Count(l => l.LogLevel == "Error" || l.Status == "Failed"),
            WarningLogs = logs.Count(l => l.LogLevel == "Warning"),
            InfoLogs = logs.Count(l => l.LogLevel == "Info"),
            SuccessOperations = logs.Count(l => l.Status == "Success"),
            FailedOperations = logs.Count(l => l.Status == "Failed"),
            InProgressOperations = logs.Count(l => l.Status == "InProgress"),
            AverageDurationMs = logs.Where(l => l.DurationMs.HasValue).Any()
                ? logs.Where(l => l.DurationMs.HasValue).Average(l => l.DurationMs!.Value)
                : 0,
            OperationTypeDistribution = logs
                .GroupBy(l => l.OperationType)
                .ToDictionary(g => g.Key, g => g.Count())
        };
    }

    /// <summary>
    /// 归档旧日志
    /// </summary>
    public async Task<int> ArchiveOldLogsAsync(int daysToKeep = 30)
    {
        var archiveDate = DateTime.UtcNow.AddDays(-daysToKeep);

        var affectedRows = await _dbProvider.Orm.Update<NodeOperationLog>()
            .Set(l => l.IsArchived, true)
            .Where(l => l.CreatedAt < archiveDate && !l.IsArchived)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("归档了 {Count} 条旧日志记录", affectedRows);
        return affectedRows;
    }

    /// <summary>
    /// 删除已归档的日志
    /// </summary>
    public async Task<int> DeleteArchivedLogsAsync()
    {
        var affectedRows = await _dbProvider.Orm.Delete<NodeOperationLog>()
            .Where(l => l.IsArchived)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("删除了 {Count} 条已归档的日志记录", affectedRows);
        return affectedRows;
    }

    /// <summary>
    /// 清理旧日志（直接删除）
    /// </summary>
    public async Task<int> CleanupOldLogsAsync(int daysToKeep = 90)
    {
        var cleanupDate = DateTime.UtcNow.AddDays(-daysToKeep);

        var affectedRows = await _dbProvider.Orm.Delete<NodeOperationLog>()
            .Where(l => l.CreatedAt < cleanupDate)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("清理了 {Count} 条旧日志记录", affectedRows);
        return affectedRows;
    }
}

/// <summary>
/// 节点操作日志统计信息
/// </summary>
public class NodeOperationLogStatistics
{
    public int TotalLogs { get; set; }
    public int ErrorLogs { get; set; }
    public int WarningLogs { get; set; }
    public int InfoLogs { get; set; }
    public int SuccessOperations { get; set; }
    public int FailedOperations { get; set; }
    public int InProgressOperations { get; set; }
    public double AverageDurationMs { get; set; }
    public Dictionary<string, int> OperationTypeDistribution { get; set; } = new();
}
